package com.bjy.qa.agent.mock.forward;

import com.alibaba.fastjson.JSONObject;
import com.bjy.qa.agent.mock.forward.http.ForwardHttpRequest;
import com.bjy.qa.agent.mock.http.BufferedHttpServletRequestWrapper;
import com.bjy.qa.agent.mock.http.MockForward;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

/**
 * 转发 service
 *
 * 参考
 *  网址：https://blog.csdn.net/m0_71777195/article/details/131186356
 *  源码：https://gitee.com/rikylee/boot-reverse-proxy
 */
@Service
public class ForwardService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    public final static int UNKNOWN_EXCEPTION_STATUS = -1;

    @Resource
    private RestTemplate restTemplate;

    /**
     * 转发请求到对应服务
     * @param request HttpServletRequest
     * @param mockForward 转发信息
     * @return
     */
    public ResponseEntity<byte[]> goForward(BufferedHttpServletRequestWrapper request, MockForward mockForward) {
        try {
            // 转发请求
            RequestEntity<byte[]> requestEntity = new ForwardHttpRequest().getRequestEntity(request, mockForward);
            ResponseEntity<byte[]> responseEntity = restTemplate.exchange(requestEntity, byte[].class); // 用byte数组处理返回结果，因为返回结果可能是字符串也可能是数据流

            return responseEntity;
        } catch (Exception e) { // 网络请求异常
            e.printStackTrace();
            logger.error("mock 转发，网络请求异常：{}", e.getMessage());
            return renderException(e.getMessage());
        }
    }

    /**
     * 网络请求异常时，生成返回的异常信息
     * @param errMsg 异常信息
     * @return
     */
    private ResponseEntity<byte[]> renderException(String errMsg) {
        // 返回异常的 json 对象
        JSONObject errResult = new JSONObject();
        errResult.put("status", UNKNOWN_EXCEPTION_STATUS);
        errResult.put("msg", errMsg);

        // 设置响应头
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.set("Content-Type", "application/json");

        // 生成响应 ResponseEntity<byte[]>
        return ResponseEntity
                .status(HttpStatus.OK)
                .headers(responseHeaders)
                .body(errResult.toJSONString().getBytes());
    }
}
